;
;  PROGRAM:  TINIT
;  VERSION:  2.1
;  AUTHOR:  RICHARD CONN
;  DATE:  25 June 83
;  DERIVATION:  TINIT.C, VERSION 1.1
;  PREVIOUS VERSIONS:  2.0 (1 Jan 83)
;
vers	equ	21

;
;	TINIT inits the TVI 950 terminal from a config file, optionally
; specified by the user.  The Config file is created by CONFIG.  TINIT
; will search along the command-search path for an indicated or default
; file, load it, and program the TVI 950 from it.
;
;	TINIT assumes that X-ON/X-OFF flow control is enabled in the
; TVI 950.  It uses this to ensure that the commands are not sent to
; the terminal too quickly.
;
;	TINIT is invoked by the following forms:
;		TINIT		<-- Program using STD.CFG
;		TINIT file	<-- Program using file.CFG
;		TINIT file.typ	<-- Program using file.typ
;		TINIT //	<-- Print Help Message
;

;
;  CP/M Constants
;
cpm	equ	0	; base of system
fcb	equ	cpm+5ch
tbuff	equ	cpm+80h
xoff	equ	13h	; ^S=X-OFF
cr	equ	0dh
lf	equ	0ah
esc	equ	1bh	; ESCAPE code for CRT Programming
delay	equ	200h	; long delay for TVI 950 to accept command
tablen	equ	80	; length of tab buffer
ullen	equ	81	; length of user line buffer
fkeylen	equ	464	; length of function key buffer

;
;  SYSLIB Routines
;
	ext	zpfind,zgpins,cst,cin,cout,crlf,print,pause,moveb
	ext	getud,logud,putud
	ext	codend,initfcb,fi0$open,f0$get,fi0$close

;
;  TVI 950 Commands
;
clear	equ	'+'	; clear screen

fctkey	equ	'|'	; begin function key defn
fctend	equ	'Y'-'@'	; end function key defn

loadusr	equ	'f'	; load user line
dispusr	equ	'g'	; display user line

sscroll	equ	'8'	; smooth scroll
hscroll	equ	'9'	; hard scroll

tabclr	equ	'3'	; all tab clear
tabset	equ	'1'	; set tab at cursor

vidnorm	equ	'd'	; normal video
vidrev	equ	'b'	; reverse video

clkon	equ	'>'	; key click on
clkoff	equ	'<'	; key click off

curs	equ	'.'	; define cursor type

;
;  General Init Settings
;
cls	equ	'+'	; clear screen
unlock	equ	'"'	; unlock keyboard
nograph	equ	'%'	; no graphics
noprot	equ	27h	; protect mode off
normi	equ	'('	; normal intensity
notabs	equ	'3'	; clear all tabs
noclick	equ	'<'	; key click off
nocopy	equ	'A'	; copy print mode off
cmode	equ	'C'	; conversation mode on
fdx	equ	'F'	; full duplex
nomonit	equ	'X'	; clear monitor mode
nobufpr	equ	'a'	; buffer print off
vid1	equ	'd'	; white on black
nopage	equ	'w'	; auto page off

;
;	This program is Copyright (c) 1982, 1983 by Richard Conn
;	All Rights Reserved
;
;	ZCPR2 and its utilities, including this one, are released
; to the public domain.  Anyone who wishes to USE them may do so with
; no strings attached.  The author assumes no responsibility or
; liability for the use of ZCPR2 and its utilities.
;
;	The author, Richard Conn, has sole rights to this program.
; ZCPR2 and its utilities may not be sold without the express,
; written permission of the author.
;

;
;  Branch to Start of Program
;
	jmp	start

;
;******************************************************************
;
;  SINSFORM -- ZCPR2 Utility Standard General Purpose Initialization Format
;
;	This data block precisely defines the data format for
; initial features of a ZCPR2 system which are required for proper
; initialization of the ZCPR2-Specific Routines in SYSLIB.
;

;
;  EXTERNAL PATH DATA
;
EPAVAIL:
	DB	0FFH	; IS EXTERNAL PATH AVAILABLE? (0=NO, 0FFH=YES)
EPADR:
	DW	40H	; ADDRESS OF EXTERNAL PATH IF AVAILABLE

;
;  INTERNAL PATH DATA
;
INTPATH:
	DB	0,0	; DISK, USER FOR FIRST PATH ELEMENT
			; DISK = 1 FOR A, '$' FOR CURRENT
			; USER = NUMBER, '$' FOR CURRENT
	DB	0,0
	DB	0,0
	DB	0,0
	DB	0,0
	DB	0,0
	DB	0,0
	DB	0,0	; DISK, USER FOR 8TH PATH ELEMENT
	DB	0	; END OF PATH

;
;  MULTIPLE COMMAND LINE BUFFER DATA
;
MCAVAIL:
	DB	0FFH	; IS MULTIPLE COMMAND LINE BUFFER AVAILABLE?
MCADR:
	DW	0FF00H	; ADDRESS OF MULTIPLE COMMAND LINE BUFFER IF AVAILABLE

;
;  DISK/USER LIMITS
;
MDISK:
	DB	4	; MAXIMUM NUMBER OF DISKS
MUSER:
	DB	31	; MAXIMUM USER NUMBER

;
;  FLAGS TO PERMIT LOG IN FOR DIFFERENT USER AREA OR DISK
;
DOK:
	DB	0FFH	; ALLOW DISK CHANGE? (0=NO, 0FFH=YES)
UOK:
	DB	0FFH	; ALLOW USER CHANGE? (0=NO, 0FFH=YES)

;
;  PRIVILEGED USER DATA
;
PUSER:
	DB	10	; BEGINNING OF PRIVILEGED USER AREAS
PPASS:
	DB	'chdir',0	; PASSWORD FOR MOVING INTO PRIV USER AREAS
	DS	41-($-PPASS)	; 40 CHARS MAX IN BUFFER + 1 for ending NULL

;
;  CURRENT USER/DISK INDICATOR
;
CINDIC:
	DB	'$'	; USUAL VALUE (FOR PATH EXPRESSIONS)

;
;  DMA ADDRESS FOR DISK TRANSFERS
;
DMADR:
	DW	80H	; TBUFF AREA

;
;  NAMED DIRECTORY INFORMATION
;
NDRADR:
	DW	00000H	; ADDRESS OF MEMORY-RESIDENT NAMED DIRECTORY
NDNAMES:
	DB	64	; MAX NUMBER OF DIRECTORY NAMES
DNFILE:
	DB	'NAMES   '	; NAME OF DISK NAME FILE
	DB	'DIR'		; TYPE OF DISK NAME FILE

;
;  REQUIREMENTS FLAGS
;
EPREQD:
	DB	0FFH	; EXTERNAL PATH?
MCREQD:
	DB	000H	; MULTIPLE COMMAND LINE?
MXREQD:
	DB	000H	; MAX USER/DISK?
UDREQD:
	DB	000H	; ALLOW USER/DISK CHANGE?
PUREQD:
	DB	000H	; PRIVILEGED USER?
CDREQD:
	DB	0FFH	; CURRENT INDIC AND DMA?
NDREQD:
	DB	000H	; NAMED DIRECTORIES?
Z2CLASS:
	DB	7	; CLASS 7
	DB	'ZCPR2'
	DS	10	; RESERVED

;
;  END OF SINSFORM -- STANDARD DEFAULT PARAMETER DATA
;
;******************************************************************
;

;
;  Default Name of CFG File
;
speed:
	db	4		; 4 MHz
cfgfile:
	db	'STD     '	; may be changed by GENINS
	db	'CFG'

;
;  Start of Program
;
start:
	call	zgpins	; init ZCPR2 buffers

	call	print
	db	'TINIT  Version '
	db	(vers/10)+'0','.',(vers mod 10)+'0',0

;
;  Allocate Buffer Space
;
	call	codend		; get start of buffer
	shld	ulbuffer	; start of underline buffer
	lxi	d,ullen		; buffer is ullen bytes
	dad	d
	shld	tabbuffer	; start of tab buffer
	lxi	d,tablen	; buffer is tablen bytes
	dad	d
	shld	fkeybuffer	; start of function key buffer

;
;  Copy Default File Name into FCB
;
	lxi	h,cfgfile	; pt to default name
	lxi	d,cfgfcb+1	; pt to FCB
	mvi	b,11		; 11 bytes
	call	moveb

;
;  Check for file name
;
	lda	fcb+1	; check for file name
	cpi	' '	; <SP> if none
	jz	program	; program from default FCB
	cpi	'/'	; help?
	jnz	start1

;
;  Print Help Message
;
	call	print
	db	cr,lf,'	TINIT is used to program a TVI 950 CRT from a'
	db	cr,lf,'Configuration File (CFG File) created by the CONFIG'
	db	cr,lf,'Program.  TINIT is invoked in the following ways --'
	db	cr,lf
	db	cr,lf,'		TINIT		<-- Program from Default'
	db	cr,lf,'		TINIT file	<-- Pgm from file.CFG'
	db	cr,lf,'		TINIT file.typ	<-- Pgm from file.typ'
	db	cr,lf,'		TINIT //	<-- Print Help'
	db	cr,lf,0
	ret

;
;  Process File Name
;
start1:
	lxi	h,fcb+1		; copy file name part
	lxi	d,cfgfcb+1	; copy into CFGFCB
	mvi	b,8		; 8 bytes
	call	moveb
	lxi	h,fcb+9		; pt to file type
	lxi	d,cfgfcb+8	; prepare to copy file type
	mvi	b,3		; 3 bytes
	mov	a,m		; any specified?
	cpi	' '		; default type if space
	cnz	moveb

;
;  Load Config File and Program TVI 950
;
program:
	lxi	d,cfgfcb	; pt to fcb
	call	initfcb		; init it
	mvi	b,0ffh		; search current dir first
	call	zpfind		; look for file
	jnz	prog1
	call	print
	db	cr,lf,'Configuration File ',0
	xchg			; HL pts to config file
	inx	h		; pt to file name
	call	prfn		; print name
	call	print
	db	' Not Found',0
	jmp	cpm

;
;  Load File Buffer into Files
;
prog1:
	call	print
	db	cr,lf,'Programming TVI 950 from File ',0
	mov	h,d		; ptr to fcb in HL also
	mov	l,e
	inx	h
	call	prfn		; print file name
	call	crlf		; new line
	call	putud
	call	logud		; log into directory
	call	fi0$open	; open file for input
	call	getch		; read char
	sta	cursor		; set cursor type
	call	getch
	sta	ffkeys		; set function key flag
	call	getch
	sta	click		; set key click
	call	getch
	sta	scroll		; set scrolling
	call	getch
	sta	ftabs		; set tab program flag
	call	getch
	sta	fuline		; set user line program flag
	call	getch
	sta	video		; set video type
	call	getch		; flush <CR> <LF>
	call	getch
	lhld	ulbuffer	; load user line if specified
	lxi	d,ullen		; size of buffer
	lda	fuline
	ora	a		; 0=no
	cnz	readbuffer	; read buffer if yes
	lhld	tabbuffer	; load tab line if specified
	lxi	d,tablen	; size of buffer
	lda	ftabs
	ora	a
	cnz	readbuffer
	lhld	fkeybuffer	; program function keys if specified
	lxi	d,fkeylen	; size of buffer
	lda	ffkeys
	ora	a
	cnz	readbuffer
	call	fi0$close	; close file
	call	getud		; restore original user/disk

;
;  Send Out All Terminial Initializations
;
	mvi	a,unlock	; unlock keyboard
	call	cmnd
	mvi	a,nograph	; no graphics
	call	cmnd
	mvi	a,noprot	; protect off
	call	cmnd
	mvi	a,normi		; normal intensity
	call	cmnd
	mvi	a,notabs	; no tabs
	call	cmnd
	mvi	a,noclick	; no key click
	call	cmnd
	mvi	a,nocopy	; no copy print mode
	call	cmnd
	mvi	a,cmode		; conversation mode on
	call	cmnd
	mvi	a,fdx		; full duplex
	call	cmnd
	mvi	a,nomonit	; no monitor mode
	call	cmnd
	mvi	a,nobufpr	; no buffer print
	call	cmnd
	mvi	a,vid1		; white on black
	call	cmnd
	mvi	a,nopage	; auto page off
	call	cmnd
	lxi	h,videom	; normal video
	call	cmnds
	lxi	h,insert	; set insert char to space
	call	cmnds
;
;  Program Cursor Type
;
	mvi	a,curs
	call	cmnd
	lda	cursor		; cursor type
	call	coutx
;
;  Program Function Keys
;
	lda	ffkeys		; any function keys?
	ora	a		; 0=no
	jz	setclick
	mvi	b,22		; 22 keys to program
	lhld	fkeybuffer	; pt to buffer
	mvi	a,'1'		; set for first function key
	sta	fkey
nxtkey:
	mov	a,m		; get first char
	ora	a		; no string?
	jz	nkey1
	push	h		; save ptr to first char
	mvi	a,fctkey	; function key follows
	call	cmnd
	lda	fkey		; print function key
	call	coutx
	call	pstr		; print string pted to by HL
	mvi	a,fctend	; end function
	call	coutx
	pop	h		; get ptr to first char
nkey1:
	lxi	d,20		; pt to next function key
	dad	d
	lda	fkey		; increment function key
	inr	a
	sta	fkey
	dcr	b		; count down
	jnz	nxtkey
	call	sleep

;
;  Set Key Click
;
setclick:
	lda	click		; from file
	call	cmnd

;
;  Set Scrolling
;
	lda	scroll		; from file
	call	cmnd

;
;  Set Tabs
;
	lda	ftabs		; set tabs?
	ora	a		; 0=no
	jz	setul
	mvi	a,tabclr	; clear all tab stops
	call	cmnd
	call	crlf		; new line
	lhld	tabbuffer	; pt to buffer
	mvi	b,tablen	; tablen chars in buffer
settabs:
	mov	a,m		; get buffer char
	inx	h		; pt to next
	cpi	'.'		; dot means set tab here
	jnz	stabs1
	mvi	a,tabset	; set tab
	call	cmnd
stabs1:
	mvi	a,' '		; space over
	call	coutx
	dcr	b		; count down
	jnz	settabs
	call	crlf		; new line

;
;  Set User Line
;
setul:
	lda	fuline		; get flag
	ora	a		; 0=no
	jz	setvideo
	mvi	a,loadusr	; load user line
	call	cmnd
	lhld	ulbuffer	; print buffer contents
	call	pstr
	mvi	a,cr		; send just <CR>
	call	coutx
	mvi	a,dispusr	; display user line
	call	cmnd
	call	sleep
;
;  Set Video
;
setvideo:
	lda	video		; get command
	call	cmnd

;
;  Done -- Clear Screen and Return to OS
;
	mvi	a,cls		; clear screen
	call	cmnd
	ret

;
;  Write Single-Char Command in A
;
cmnd:
	push	psw		; save command
	mvi	a,esc
	call	coutx		; send ESC
	pop	psw
	call	coutx		; send char
	ret

;
;  Write String Command pted to by HL
;
cmnds:
	mvi	a,esc		; send ESC
	call	coutx		; and fall thru to pstr
;
;  Write String Pted to by HL
;
pstr:
	push	h		; save HL
pstr1:
	mov	a,m		; get char
	ora	a		; done?
	jz	pstr2
	inx	h		; pt to next
	call	coutx		; send char
	jmp	pstr1
pstr2:
	pop	h		; get HL
	ret
;
;  Print File Name pted to by HL
;
prfn:
	push	b		; save BC
	mvi	b,8
	call	prfn1		; print name part
	mvi	a,'.'
	call	coutx
	mvi	b,3		; print type
	call	prfn1
	pop	b		; restore BC
	ret
prfn1:
	mov	a,m		; get char
	call	coutx		; print char
	inx	h		; pt to next
	dcr	b		; count down
	jnz	prfn1
	ret

;
;  Sleep 0.1 secs
;
sleep:
	push	h		; save regs
	push	b
	push	psw
	lda	speed		; get processor speed
	mov	b,a		; ... in B
	lxi	h,1		; 0.1 secs
	call	pause
	pop	psw		; restore regs
	pop	b
	pop	h
	ret

;
;  Output Char in A to Console, but Check for X-OFF first
;
coutx:
	push	psw	; save char
	call	cst	; char pending?
	ora	a	; nz=not rda
	jnz	coutx1
	call	cin	; get char
	cpi	xoff	; pause?
	jnz	coutx1
	call	cin	; accept any char for continue
coutx1:
	pop	psw	; get char
	jmp	cout	; send it

;
;  Get Char from File with Possible Abort
;
getch:
	call	f0$get		; get char
	rz			; char OK
	call	print
	db	cr,lf,'File Read Error -- Aborting',0
	jmp	cpm

;
;  Read into buffer pted to by HL for DE bytes
;
readbuffer:
	call	getch		; get byte from file
	mov	m,a		; put byte
	inx	h		; pt to next
	dcx	d		; count down
	mov	a,d		; done?
	ora	e
	jnz	readbuffer
	call	getch		; flush <CR> <LF>
	jmp	getch

;
;  Some Command Strings
;
videom:
	db	'G0',0
insert:
	db	'e ',0

;
;  Buffers
;
cursor:	ds	1
fuline:	ds	1
video:	ds	1
ftabs:	ds	1
fkey:	ds	1
click:	ds	1
scroll:	ds	1
ffkeys:	ds	1
ulbuffer:
	ds	2	; ptr
tabbuffer:
	ds	2	; ptr
fkeybuffer:
	ds	2	; ptr
cfgfcb:
	ds	36	; FCB for config file

	end
